package com.zenithmind.library.controller;

import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.library.pojo.dto.FineRecordCreateDTO;
import com.zenithmind.library.pojo.dto.FineRecordUpdateDTO;
import com.zenithmind.library.pojo.query.FineRecordQuery;
import com.zenithmind.library.pojo.vo.FineRecordVO;
import com.zenithmind.library.service.FineRecordService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;

/**
 * 罚金记录管理控制器
 * 遵循单一职责原则：只负责罚金记录相关的HTTP请求处理
 * 遵循依赖倒置原则：依赖抽象接口而非具体实现
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@RestController
@RequestMapping("/api/library/fine-records")
@RequiredArgsConstructor
@Tag(name = "罚金记录管理", description = "罚金记录的增删改查、支付、减免、统计等功能")
public class FineRecordController {

    private final FineRecordService fineRecordService;

    @GetMapping("/page")
    @Operation(summary = "分页查询罚金记录", description = "根据条件分页查询罚金记录列表")
    @PreAuthorize("hasAuthority('library:fine-record:query')")
    public Result<PageResult<FineRecordVO>> getFineRecordPage(@Valid FineRecordQuery query) {
        log.info("分页查询罚金记录，查询条件：{}", query);
        PageResult<FineRecordVO> result = fineRecordService.getFineRecordPage(query);
        return Result.success(result);
    }

    @GetMapping("/{id}")
    @Operation(summary = "查询罚金记录详情", description = "根据ID查询罚金记录详细信息")
    @PreAuthorize("hasAuthority('library:fine-record:query')")
    public Result<FineRecordVO> getFineRecordById(
            @Parameter(description = "罚金记录ID", required = true)
            @PathVariable String id) {
        log.info("查询罚金记录详情，ID：{}", id);
        return fineRecordService.getFineRecordById(id);
    }

    @GetMapping("/user/{userId}")
    @Operation(summary = "查询用户的罚金记录", description = "根据用户ID查询该用户的罚金记录列表")
    @PreAuthorize("hasAuthority('library:fine-record:query')")
    public Result<List<FineRecordVO>> getFineRecordsByUserId(
            @Parameter(description = "用户ID", required = true)
            @PathVariable String userId,
            @Parameter(description = "支付状态")
            @RequestParam(required = false) Integer status) {
        log.info("查询用户的罚金记录，用户ID：{}，状态：{}", userId, status);
        return fineRecordService.getFineRecordsByUserId(userId, status);
    }

    @GetMapping("/borrow-record/{borrowRecordId}")
    @Operation(summary = "查询借阅记录的罚金记录", description = "根据借阅记录ID查询相关的罚金记录")
    @PreAuthorize("hasAuthority('library:fine-record:query')")
    public Result<List<FineRecordVO>> getFineRecordsByBorrowRecordId(
            @Parameter(description = "借阅记录ID", required = true)
            @PathVariable String borrowRecordId) {
        log.info("查询借阅记录的罚金记录，借阅记录ID：{}", borrowRecordId);
        return fineRecordService.getFineRecordsByBorrowRecordId(borrowRecordId);
    }

    @PostMapping
    @Operation(summary = "创建罚金记录", description = "创建新的罚金记录")
    @PreAuthorize("hasAuthority('library:fine-record:create')")
    public Result<FineRecordVO> createFineRecord(@Valid @RequestBody FineRecordCreateDTO createDTO) {
        log.info("创建罚金记录，参数：{}", createDTO);
        return fineRecordService.createFineRecord(createDTO);
    }

    @PutMapping("/{id}")
    @Operation(summary = "更新罚金记录", description = "更新罚金记录信息")
    @PreAuthorize("hasAuthority('library:fine-record:update')")
    public Result<FineRecordVO> updateFineRecord(
            @Parameter(description = "罚金记录ID", required = true)
            @PathVariable String id,
            @Valid @RequestBody FineRecordUpdateDTO updateDTO) {
        log.info("更新罚金记录，ID：{}，参数：{}", id, updateDTO);
        return fineRecordService.updateFineRecord(id, updateDTO);
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除罚金记录", description = "删除指定的罚金记录")
    @PreAuthorize("hasAuthority('library:fine-record:delete')")
    public Result<Void> deleteFineRecord(
            @Parameter(description = "罚金记录ID", required = true)
            @PathVariable String id) {
        log.info("删除罚金记录，ID：{}", id);
        return fineRecordService.deleteFineRecord(id);
    }

    @DeleteMapping("/batch")
    @Operation(summary = "批量删除罚金记录", description = "批量删除多个罚金记录")
    @PreAuthorize("hasAuthority('library:fine-record:delete')")
    public Result<Void> batchDeleteFineRecords(
            @Parameter(description = "罚金记录ID列表", required = true)
            @RequestBody List<String> ids) {
        log.info("批量删除罚金记录，数量：{}", ids.size());
        return fineRecordService.batchDeleteFineRecords(ids);
    }

    @PostMapping("/{id}/pay")
    @Operation(summary = "支付罚金", description = "支付指定的罚金记录")
    @PreAuthorize("hasAuthority('library:fine-record:pay')")
    public Result<Void> payFine(
            @Parameter(description = "罚金记录ID", required = true)
            @PathVariable String id,
            @Parameter(description = "支付方式", required = true)
            @RequestParam String paymentMethod,
            @Parameter(description = "交易ID", required = true)
            @RequestParam String transactionId) {
        log.info("支付罚金，ID：{}，支付方式：{}，交易ID：{}", id, paymentMethod, transactionId);
        return fineRecordService.payFine(id, paymentMethod, transactionId);
    }

    @PostMapping("/{id}/waive")
    @Operation(summary = "减免罚金", description = "减免指定的罚金记录")
    @PreAuthorize("hasAuthority('library:fine-record:waive')")
    public Result<Void> waiveFine(
            @Parameter(description = "罚金记录ID", required = true)
            @PathVariable String id,
            @Parameter(description = "减免金额", required = true)
            @RequestParam BigDecimal waiveAmount,
            @Parameter(description = "减免原因", required = true)
            @RequestParam String waiveReason) {
        log.info("减免罚金，ID：{}，减免金额：{}，减免原因：{}", id, waiveAmount, waiveReason);
        return fineRecordService.waiveFine(id, waiveAmount, waiveReason);
    }

    @PostMapping("/{id}/cancel")
    @Operation(summary = "取消罚金", description = "取消指定的罚金记录")
    @PreAuthorize("hasAuthority('library:fine-record:cancel')")
    public Result<Void> cancelFine(
            @Parameter(description = "罚金记录ID", required = true)
            @PathVariable String id,
            @Parameter(description = "取消原因", required = true)
            @RequestParam String cancelReason) {
        log.info("取消罚金，ID：{}，取消原因：{}", id, cancelReason);
        return fineRecordService.cancelFine(id, cancelReason);
    }

    @GetMapping("/calculate-overdue-fine")
    @Operation(summary = "计算逾期罚金", description = "根据借阅记录和逾期天数计算罚金金额")
    @PreAuthorize("hasAuthority('library:fine-record:calculate')")
    public Result<BigDecimal> calculateOverdueFine(
            @Parameter(description = "借阅记录ID", required = true)
            @RequestParam String borrowRecordId,
            @Parameter(description = "逾期天数", required = true)
            @RequestParam Integer overdueDays) {
        log.info("计算逾期罚金，借阅记录ID：{}，逾期天数：{}", borrowRecordId, overdueDays);
        return fineRecordService.calculateOverdueFine(borrowRecordId, overdueDays);
    }

    @PostMapping("/generate-overdue-fine")
    @Operation(summary = "生成逾期罚金记录", description = "为指定借阅记录自动生成逾期罚金记录")
    @PreAuthorize("hasAuthority('library:fine-record:generate')")
    public Result<FineRecordVO> generateOverdueFine(
            @Parameter(description = "借阅记录ID", required = true)
            @RequestParam String borrowRecordId) {
        log.info("生成逾期罚金记录，借阅记录ID：{}", borrowRecordId);
        return fineRecordService.generateOverdueFine(borrowRecordId);
    }

    @GetMapping("/user/{userId}/unpaid-amount")
    @Operation(summary = "获取用户未支付罚金总额", description = "获取指定用户的未支付罚金总额")
    @PreAuthorize("hasAuthority('library:fine-record:query')")
    public Result<BigDecimal> getUnpaidFineAmount(
            @Parameter(description = "用户ID", required = true)
            @PathVariable String userId) {
        log.info("获取用户未支付罚金总额，用户ID：{}", userId);
        return fineRecordService.getUnpaidFineAmount(userId);
    }

    @GetMapping("/statistics")
    @Operation(summary = "获取罚金统计信息", description = "获取罚金统计信息")
    @PreAuthorize("hasAuthority('library:fine-record:query')")
    public Result<FineRecordService.FineStatisticsVO> getFineStatistics(
            @Parameter(description = "用户ID（可选）")
            @RequestParam(required = false) String userId) {
        log.info("获取罚金统计信息，用户ID：{}", userId);
        return fineRecordService.getFineStatistics(userId);
    }

    @PostMapping("/import")
    @Operation(summary = "导入罚金记录", description = "批量导入罚金记录数据")
    @PreAuthorize("hasAuthority('library:fine-record:import')")
    public Result<String> importFineRecords(
            @Parameter(description = "罚金记录数据列表", required = true)
            @RequestBody List<FineRecordCreateDTO> fineRecords) {
        log.info("导入罚金记录，数量：{}", fineRecords.size());
        return fineRecordService.importFineRecords(fineRecords);
    }

    @PostMapping("/export")
    @Operation(summary = "导出罚金记录", description = "根据条件导出罚金记录数据")
    @PreAuthorize("hasAuthority('library:fine-record:export')")
    public Result<String> exportFineRecords(@RequestBody FineRecordQuery query) {
        log.info("导出罚金记录，查询条件：{}", query);
        return fineRecordService.exportFineRecords(query);
    }
}
